﻿#include "Plot.h"
#include "MainWindow.h"

CCoreSPCN *pSPCN;
config	*cfg;

double phi(double &x)
{
	// constants
	double a1 =  0.254829592;
	double a2 = -0.284496736;
	double a3 =  1.421413741;
	double a4 = -1.453152027;
	double a5 =  1.061405429;
	double p  =  0.3275911;

	// Save the sign of x
	int sign = 1;
	if (x < 0)
		sign = -1;
	x = fabs(x)/sqrt(2.0);

	// A&S formula 7.1.26
	double t = 1.0/(1.0 + p*x);
	double y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*exp(-x*x);

	return 0.5*(1.0 + sign*y);
}

Histogram::Histogram(const QString &title, const QColor &symbolColor):
QwtPlotHistogram(title)
{
	setStyle(QwtPlotHistogram::Columns);

	setColorHist(symbolColor);
}

void Histogram::setColorHist(const QColor &symbolColor, int alpha)
{
	QColor color = symbolColor;
	color.setAlpha( alpha);

	setPen(QPen(Qt::black));
	setBrush(QBrush(color));

	QwtColumnSymbol *symbol = new QwtColumnSymbol(QwtColumnSymbol::Box);
	symbol->setFrameStyle(QwtColumnSymbol::Raised);
	symbol->setLineWidth(2);
	symbol->setPalette(QPalette(color));
	setSymbol(symbol);
}

void Histogram::setValues(uint numValues, double *values)
{
	QVector<QwtIntervalSample> samples(numValues);
	for ( uint i = 0; i < numValues; i++ )
	{
		QwtInterval interval(double(i), i + 1.0);
		interval.setBorderFlags(QwtInterval::ExcludeMaximum);

		samples[i] = QwtIntervalSample(values[i], interval);
	}

	setData(new QwtIntervalSeriesData(samples));
}

Plot::Plot(QWidget *parent):
QwtPlot(parent)
{}

void Plot::setupHistogram()
{
	setCanvasBackground(QColor(Qt::transparent));
	plotLayout()->setAlignCanvasToScales(true);
	setAxisTitle(QwtPlot::yLeft, "Cond");
	setAxisTitle(QwtPlot::xBottom, "Experiments");
	legend = new QwtLegend;
	legend->setItemMode(QwtLegend::CheckableItem);
	insertLegend(legend, QwtPlot::RightLegend);

	QwtPlotGrid *grid = new QwtPlotGrid;
	grid->enableX(false);
	grid->enableY(true);
	grid->enableXMin(false);
	grid->enableYMin(false);
	grid->setMajPen(QPen(Qt::black, 0, Qt::DotLine));
	grid->attach(this);

	connect(this, SIGNAL(legendChecked(QwtPlotItem *, bool)),
		SLOT(showItem(QwtPlotItem *, bool)));

	replot(); // creating the legend items

	setAutoReplot(true);
}

void Plot::populateHistogram(char* lawName,Qt::GlobalColor color)
{
	grid.push_back(new QwtPlotGrid);
	grid.back()->enableX(true);
	grid.back()->enableY(true);
	grid.back()->enableXMin(false);
	grid.back()->enableYMin(false);
	grid.back()->setMajPen(QPen(Qt::black, 0, Qt::DotLine));
	grid.back()->attach(this);

	histogramCond.push_back(new Histogram(lawName, color));

	int ValueNum = pSPCN->getPerfom();

	std::vector<double> tmpCN;
	for (int i=0; i < ValueNum; i++)
		tmpCN.push_back(pSPCN->CondNum[i].val);

	histogramCond.back()->setValues(
		ValueNum, &tmpCN.at(0));

	histogramCond.back()->attach(this);

	items = itemList(QwtPlotItem::Rtti_PlotHistogram);

	legendItem.push_back((QwtLegendItem *)legend->find(items[items.size()-1]));

	if (items.size() > 1)
	{
		legendItem.at(items.size() - 2 )->setChecked(false);
		items.at(items.size() - 2 )->setVisible(false);
	}

	legendItem.back()->setChecked(true);
	items.back()->setVisible(true);
	replot();
}

void Plot::clearHistogram()
{
	// очищаем историю гистограмы
	legend->clear();
	// очищаем данніе всех єкспирементов
	for (int i = 0; i < cfg->coutModeling; i++)
	{
		histogramCond.at(i)->setVisible(false);
		histogramCond.at(i)->detach();

		grid.at(i)->setVisible(false);
		grid.at(i)->detach();
	}
	grid.clear();
	histogramCond.clear();
	legendItem.clear();
}

void Plot::setupFunction()
{
	setCanvasBackground(QColor(Qt::darkGray));
	plotLayout()->setAlignCanvasToScales(true);

	zoomer = new QwtPlotZoomer(this->canvas(),false);
	zoomer->setRubberBandPen(QColor(Qt::blue));
	zoomer->setTrackerPen(QColor(Qt::red));
	d_intervalCurve = new QwtPlotIntervalCurve;
	
	replot();
}
void Plot::populateFunction(int idPlot)
{
	//assert(idPlot>1);
// настройка вида и свойств сетки
	grid.push_back(new QwtPlotGrid);
	grid.back()->enableX(true);
	grid.back()->enableY(true);
	grid.back()->enableXMin(false);
	grid.back()->enableYMin(false);
	grid.back()->setMajPen(QPen(Qt::black, 0, Qt::DotLine));
	grid.back()->attach(this);

	if(idPlot == 0)
	{
		const int varSize = pSPCN->_statistic.CondStat.size();
		const int CoutFreq = pSPCN->getPerfom();

		std::vector<double> freqArr(varSize);
		for ( int i = 0; i < varSize; i++ )
		{
			float id =  pSPCN->_statistic.CondStat.at(i).id;
			freqArr.push_back(id / CoutFreq);
			//double valCond = pSPCN->_statistic.CondStat.at(i).val;
			_dataInterval.push_back(QwtIntervalSample(/*valCond*/double(i),QwtInterval(double(0),freqArr.back())));
		}
	
		insertData(_dataInterval, Qt::blue);
		// - поиск максимального значения относительной частоты числа обусловленности
		float maxFreq = *std::max_element (freqArr.begin(),freqArr.end());
		this->setAxisScale( QwtPlot::yLeft, 0, maxFreq, 0 );
		this->setAxisScale( QwtPlot::xBottom, 0, varSize, 0 );

		updateAxes();
		replot();
		// первоначальное положение зумера берется из канвы
		zoomer->setZoomBase(false);
	}

	if(idPlot == 1)
	{
		const int _coutPerf = pSPCN->getPerfom();
		double x = 0.0,x_next=0.0;
		double dimCond = 1.0 / _coutPerf;
		std::vector<double> _valArr;
		double j = 1;
		for ( int i = 0; i <= _coutPerf - 1; i++)
		{
			x = pSPCN->CondNum.at(i).val;
			//x_next = pSPCN->CondNum.at(i+1).val;
			double val = dimCond * j;
			/*double Pi = (phi(x) - phi(x_next));*/
			_valArr.push_back(val);
			
			/*double */
			//if(i)

			//double valCond = 
			_dataInterval.push_back(QwtIntervalSample(x ,QwtInterval(double(0),_valArr.back())));
			j += 1;
		}

		insertData(_dataInterval, Qt::red);

		this->setAxisScale(QwtPlot::yLeft, 0,1,0);
		// получить максимальное значение числа обусловленности
		double maxCond = pSPCN->getMaxCond();
		double minCond = pSPCN->getMinCond();
		this->setAxisScale(QwtPlot::xBottom, minCond, maxCond, 0);

		updateAxes();
		replot();
		// первоначальное положение зумера берется из канвы
		zoomer->setZoomBase(false);
	}
}
void Plot::clearFunktion()
{
	int var = pSPCN->_statistic.CondStat.size();
	for (int i = 0; i < cfg->coutAnaliz; i++)
	{
		grid.at(i)->setVisible(false);
		grid.at(i)->detach();
	}
	grid.clear();
	_dataInterval.clear();

	d_intervalCurve->setVisible(false);
	d_intervalCurve->detach();
}

void Plot::showItem(QwtPlotItem *item, bool on)
{
	item->setVisible(on);
}

void Plot::insertData(QVector<QwtIntervalSample>& samples,const QColor &color)
{
	d_intervalCurve->setRenderHint(QwtPlotItem::RenderAntialiased);
	d_intervalCurve->setPen(QPen(Qt::white));

	QColor bg(color);
	bg.setAlpha(150);
	d_intervalCurve->setBrush(QBrush(bg));
	d_intervalCurve->setStyle(QwtPlotIntervalCurve::Tube);

	d_intervalCurve->setSamples(samples);

	d_intervalCurve->attach(this);

	d_intervalCurve->setVisible(true);
}

